<template>
  <view
    class="min-h-screen bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors duration-300">
    <!-- 顶部导航 -->
    <view class="sticky top-0 z-50 bg-white dark:bg-gray-800 shadow-sm">
      <view class="container mx-auto px-4 py-3 flex justify-between items-center">
        <text class="text-xl font-bold text-blue-600 dark:text-blue-400">前端面试宝典</text>

        <view class="flex items-center gap-3">
          <button class="p-2 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"
            @click="toggleDarkMode">
            <i class="fa" :class="isDarkMode ? 'fa-sun-o' : 'fa-moon-o'"></i>
          </button>

          <button class="p-2 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"
            @click="showSearch = !showSearch">
            <i class="fa fa-search"></i>
          </button>
        </view>
      </view>

      <!-- 搜索框 -->
      <view v-if="showSearch" class="container mx-auto px-4 pb-3 animate-fadeIn">
        <view class="relative">
          <input type="text" v-model="searchQuery" placeholder="搜索面试题..."
            class="w-full py-2 px-10 rounded-lg bg-gray-100 dark:bg-gray-700 border border-gray-200 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all">
          <i class="fa fa-search absolute left-3 top-1/2 -translate-y-1/2 text-gray-400"></i>
          <button v-if="searchQuery"
            class="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
            @click="searchQuery = ''">
            <i class="fa fa-times"></i>
          </button>
        </view>
      </view>
    </view>

    <!-- 主内容区 -->
    <view class="container mx-auto px-4 py-6 flex flex-col md:flex-row gap-6">
      <!-- 侧边栏分类 -->
      <view class="w-full md:w-64 lg:w-72 shrink-0">
        <view class="bg-white dark:bg-gray-800 rounded-xl shadow-sm overflow-hidden sticky top-24">
          <view class="p-4 border-b border-gray-200 dark:border-gray-700">
            <text class="font-medium">面试分类</text>
          </view>

          <view class="p-2">
            <view v-for="(category, index) in categories" :key="index"
              class="category-item px-4 py-3 rounded-lg mb-1 cursor-pointer flex items-center gap-3 transition-all"
              :class="{
                'bg-blue-50 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400 font-medium': activeCategory === index,
                'hover:bg-gray-100 dark:hover:bg-gray-700/50': activeCategory !== index
              }" @click="activeCategory = index; scrollToTop()">
              <i class="fa" :class="category.icon"></i>
              <text>{{ category.name }}</text>
            </view>
          </view>
        </view>
      </view>

      <!-- 面试题内容 -->
      <view class="flex-1">
        <view class="mb-6 flex justify-between items-center">
          <text class="text-2xl font-bold">{{ categories[activeCategory].name }}</text>
          <text class="text-sm text-gray-500 dark:text-gray-400">{{ filteredQuestions.length }} 个问题</text>
        </view>

        <!-- 问题列表 -->
        <view class="space-y-4">
          <view v-for="(question, qIndex) in filteredQuestions" :key="qIndex"
            class="bg-white dark:bg-gray-800 rounded-xl shadow-sm overflow-hidden transition-all hover:shadow-md">
            <view class="p-5">
              <!-- 问题部分 -->
              <view class="flex items-start gap-3 mb-4">
                <view
                  class="flex-shrink-0 w-6 h-6 rounded-full bg-blue-100 dark:bg-blue-900/50 flex items-center justify-center mt-0.5">
                  <text class="text-blue-600 dark:text-blue-400 text-sm font-medium">{{ qIndex + 1 }}</text>
                </view>
                <view>
                  <text class="font-medium text-lg">{{ question.title }}</text>
                </view>
              </view>

              <!-- 答案部分 -->
              <view class="pl-9">
                <view v-if="question.type === 'note'" class="prose dark:prose-invert max-w-none">
                  <p v-for="(para, pIndex) in question.content" :key="pIndex" class="mb-3">
                    {{ para }}
                  </p>
                </view>

                <view v-else class="prose dark:prose-invert max-w-none">
                  <p v-for="(para, pIndex) in question.answer" :key="pIndex" class="mb-3">
                    {{ para }}
                  </p>

                  <!-- 代码示例 -->
                  <view v-if="question.code" class="my-4 bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto">
                    <pre><code>{{ question.code }}</code></pre>
                  </view>
                </view>
              </view>
            </view>

            <!-- 交互按钮 -->
            <view
              class="px-5 py-3 bg-gray-50 dark:bg-gray-800/50 border-t border-gray-100 dark:border-gray-700 flex justify-between items-center">
              <button
                class="flex items-center gap-1 text-sm text-gray-500 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
                <i class="fa" :class="question.starred ? 'fa-star text-yellow-400' : 'fa-star-o'"></i>
                <text>收藏</text>
              </button>

              <button
                class="flex items-center gap-1 text-sm text-gray-500 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
                <i class="fa fa-share-alt"></i>
                <text>分享</text>
              </button>
            </view>
          </view>
        </view>

        <!-- 空状态 -->
        <view v-if="filteredQuestions.length === 0" class="flex flex-col items-center justify-center py-16 text-center">
          <i class="fa fa-search text-5xl text-gray-300 dark:text-gray-600 mb-4"></i>
          <text class="text-gray-500 dark:text-gray-400 text-lg">没有找到相关面试题</text>
          <text class="text-gray-400 dark:text-gray-500 mt-2">尝试使用其他关键词搜索</text>
          <button class="mt-4 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
            @click="searchQuery = ''">
            清除搜索
          </button>
        </view>
      </view>
    </view>

    <!-- 底部 -->
    <view class="mt-12 py-6 border-t border-gray-200 dark:border-gray-800">
      <view class="container mx-auto px-4 text-center text-gray-500 dark:text-gray-400 text-sm">
        <text>前端面试宝典 © 2023</text>
      </view>
    </view>
  </view>
</template>

<script setup>
  import {
    ref,
    computed,
    onMounted
  } from 'vue';

  // 状态管理
  const activeCategory = ref(0);
  const showSearch = ref(false);
  const searchQuery = ref('');
  const isDarkMode = ref(false);

  // 切换深色模式
  const toggleDarkMode = () => {
    isDarkMode.value = !isDarkMode.value;
    document.documentElement.classList.toggle('dark', isDarkMode.value);
  };

  // 监听系统深色模式
  onMounted(() => {
    const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
    isDarkMode.value = prefersDark;
    document.documentElement.classList.toggle('dark', prefersDark);
  });

  // 分类数据
  const categories = ref([{
      name: 'JavaScript',
      icon: 'fa-code'
    },
    {
      name: 'Vue',
      icon: 'fa-vuejs'
    },
    {
      name: 'HTML',
      icon: 'fa-html5'
    },
    {
      name: 'CSS',
      icon: 'fa-css3'
    },
    {
      name: '面试注意事项',
      icon: 'fa-lightbulb-o'
    }
  ]);

  // 面试题数据
  const questions = ref([
    // JavaScript 面试题
    {
      category: 0,
      title: '什么是闭包？闭包有什么用途？',
      answer: [
        '闭包是指有权访问另一个函数作用域中变量的函数，通常是在嵌套函数中实现的。',
        '当内部函数被保存到外部时，将会生成闭包。闭包会导致原有作用域链不释放，造成内存泄漏。',
        '闭包的主要用途有：',
        '1. 实现私有变量和方法',
        '2. 用于函数防抖、节流',
        '3. 模块化开发，避免全局变量污染',
        '4. 柯里化函数'
      ],
      code: `// 闭包示例
function outer() {
  let count = 0;
  return function inner() {
    count++;
    return count;
  }
}

const counter = outer();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3`
    },
    {
      category: 0,
      title: 'Promise 有哪几种状态？如何理解 Promise 的链式调用？',
      answer: [
        'Promise 有三种状态：pending（进行中）、fulfilled（已成功）和 rejected（已失败）。',
        '状态一旦改变，就会永久保持该状态，不会再发生变化。',
        'Promise 的链式调用是指每个 then 方法都会返回一个新的 Promise 实例，因此可以链式调用。',
        '这样可以解决回调地狱问题，使异步操作的代码更加清晰、易读。'
      ],
      code: `// Promise 链式调用示例
new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1);
  }, 1000);
})
.then(value => {
  console.log(value); // 1
  return value * 2;
})
.then(value => {
  console.log(value); // 2
  return value * 2;
})
.then(value => {
  console.log(value); // 4
});`
    },
    {
      category: 0,
      title: '什么是原型链？它在 JavaScript 中有什么作用？',
      answer: [
        '原型链是 JavaScript 中实现继承的主要方式。每个对象都有一个原型对象，对象可以从原型对象继承属性和方法。',
        '当访问一个对象的属性或方法时，如果该对象本身没有这个属性或方法，JavaScript 会沿着原型链向上查找，直到找到为止。',
        '如果在整个原型链中都找不到，则返回 undefined。',
        '原型链的顶端是 null。'
      ],
      code: `// 原型链示例
function Person(name) {
  this.name = name;
}

Person.prototype.sayHello = function() {
  console.log(\`Hello, \${this.name}!\`);
};

const person = new Person('John');
person.sayHello(); // Hello, John!

// 原型链: person -> Person.prototype -> Object.prototype -> null`
    },

    // Vue 面试题
    {
      category: 1,
      title: 'Vue 3 与 Vue 2 相比有哪些主要变化？',
      answer: [
        '1. 响应式系统：Vue 3 使用 Proxy 代替 Object.defineProperty，提供了更好的响应式支持，包括对数组、Map、Set 的原生支持。',
        '2. 组合式 API：引入了 Composition API（setup 函数），可以更好地组织组件逻辑，替代了 Vue 2 中的 Options API。',
        '3. 性能提升：重写了虚拟 DOM 实现，编译时进行了更多优化，渲染性能提升约 55%。',
        '4. 更小的体积：通过 Tree-shaking 减少了打包体积。',
        '5. 更好的 TypeScript 支持：Vue 3 本身使用 TypeScript 编写，提供了更好的类型推断。',
        '6. 新的生命周期钩子：如 onMounted、onUpdated 等，与 Composition API 配合使用。',
        '7. 片段（Fragments）：组件可以有多个根节点。'
      ]
    },
    {
      category: 1,
      title: 'Vue 中的 computed 和 watch 有什么区别？',
      answer: [
        'computed（计算属性）：',
        '1. 主要用于依赖响应式数据进行计算并返回结果',
        '2. 具有缓存机制，只有当依赖的数据发生变化时才会重新计算',
        '3. 不能直接修改计算属性的值，应该通过修改依赖的响应式数据来间接修改',
        '4. 适用于模板中需要复杂计算的场景',
        '',
        'watch（监听器）：',
        '1. 主要用于监听响应式数据的变化，并执行相应的副作用（如异步操作）',
        '2. 没有缓存机制，数据变化时总会执行回调函数',
        '3. 可以监听单个或多个数据的变化',
        '4. 适用于需要在数据变化时执行异步操作或复杂逻辑的场景'
      ],
      code: `// computed 示例
const count = ref(0);
const doubleCount = computed(() => {
  return count.value * 2;
});

// watch 示例
watch(count, (newValue, oldValue) => {
  console.log(\`count 从 \${oldValue} 变为 \${newValue}\`);
});`
    },

    // HTML 面试题
    {
      category: 2,
      title: 'HTML5 新增了哪些重要特性？',
      answer: [
        '1. 语义化标签：如 <header>、<footer>、<nav>、<article>、<section> 等，提高了代码的可读性和SEO友好性。',
        '2. 增强型表单：新增了多种输入类型（如 email、url、number、date 等）和表单属性（如 required、placeholder、pattern 等）。',
        '3. 本地存储：提供了 localStorage 和 sessionStorage，允许在客户端存储数据。',
        '4. 多媒体支持：新增 <video> 和 <audio> 标签，原生支持音视频播放。',
        '5. Canvas 绘图：提供了 <canvas> 元素，允许通过 JavaScript 动态绘制图形。',
        '6. SVG 支持：原生支持 SVG 矢量图形。',
        '7. 地理定位：通过 Geolocation API 可以获取用户的地理位置。',
        '8. Web Workers：允许在后台线程中运行 JavaScript，避免阻塞主线程。',
        '9. WebSocket：提供了全双工通信渠道，允许客户端和服务器之间进行实时通信。'
      ]
    },

    // CSS 面试题
    {
      category: 3,
      title: '什么是 BFC？如何创建 BFC？BFC 有什么作用？',
      answer: [
        'BFC（Block Formatting Context，块级格式化上下文）是 Web 页面中盒模型布局的一种渲染模式，是一个独立的渲染区域。',
        '',
        '创建 BFC 的方法：',
        '1. 根元素（<html>）',
        '2. 浮动元素（float 值不为 none）',
        '3. 绝对定位元素（position 为 absolute 或 fixed）',
        '4. 行内块元素（display 为 inline-block）',
        '5. overflow 值不为 visible 的块元素',
        '6. display 值为 flow-root 的元素',
        '',
        'BFC 的作用：',
        '1. 解决浮动元素导致的父元素高度塌陷问题',
        '2. 阻止元素被浮动元素覆盖',
        '3. 阻止margin重叠'
      ],
      code: `// 创建 BFC 示例
.parent {
  /* 创建 BFC */
  overflow: hidden;
}

.child {
  float: left;
  width: 100px;
  height: 100px;
  background: red;
}`
    },
    {
      category: 3,
      title: 'CSS 中常见的布局方式有哪些？',
      answer: [
        '1. 流式布局（Flow Layout）：默认的布局方式，元素按照正常的文档流排列。',
        '2. 浮动布局（Float Layout）：使用 float 属性使元素脱离文档流，向左或向右浮动。',
        '3. 定位布局（Position Layout）：使用 position 属性控制元素的位置，包括 static、relative、absolute、fixed、sticky。',
        '4. 弹性盒布局（Flexbox Layout）：使用 display: flex 创建弹性容器，通过弹性盒属性灵活控制子元素的排列方式。',
        '5. 网格布局（Grid Layout）：使用 display: grid 创建网格容器，将页面划分为二维网格，精确控制元素的位置和大小。',
        '6. 表格布局（Table Layout）：使用 display: table 等属性使元素像表格一样排列。',
        '7. 多列布局（Multi-column Layout）：使用 column-count 等属性将内容分为多列显示。',
        '8. 响应式布局：结合媒体查询（media queries）和其他布局方式，使页面在不同设备上有良好的显示效果。'
      ]
    },

    // 面试注意事项
    {
      category: 4,
      type: 'note',
      title: '技术面试前的准备',
      content: [
        '1. 复习核心基础知识：巩固 JavaScript、HTML、CSS 等前端基础知识，特别是自己薄弱的部分。',
        '2. 熟悉所用框架：深入理解你所使用的框架（如 Vue、React）的核心原理和常用 API。',
        '3. 准备项目介绍：梳理自己做过的项目，能够清晰地讲解项目背景、技术栈、你的职责和遇到的挑战及解决方案。',
        '4. 练习编程题：提前练习常见的算法题和编程题，熟悉常见的数据结构和算法。',
        '5. 了解公司：研究面试公司的业务、技术栈和企业文化，以便更好地回答相关问题。',
        '6. 准备问题：准备一些想问面试官的问题，这既能体现你的积极性，也能帮助你了解公司。'
      ]
    },
    {
      category: 4,
      type: 'note',
      title: '面试中的注意事项',
      content: [
        '1. 保持良好的心态：面试是双向选择的过程，保持自信但不要自负。',
        '2. 听清问题再回答：确保自己理解了问题再作答，不明白的地方可以礼貌地询问。',
        '3. 思路清晰：回答问题时尽量结构化，先说结论，再分点阐述。',
        '4. 实事求是：不会的问题不要假装会，可以说"这个问题我不太熟悉，但我可以尝试分析一下..."。',
        '5. 展示解决问题的能力：面试官不仅关注答案本身，更关注你解决问题的思路和方法。',
        '6. 注意肢体语言：保持眼神交流，坐姿端正，展现你的自信和专业态度。',
        '7. 控制回答时间：不要过于冗长，也不要过于简短，确保信息完整且简洁。'
      ]
    },
    {
      category: 4,
      type: 'note',
      title: '面试后的跟进',
      content: [
        '1. 发送感谢信：面试结束后 24 小时内，可以给面试官发送一封简短的感谢信，表达对面试机会的感谢和对职位的兴趣。',
        '2. 总结经验：无论面试结果如何，都要总结经验教训，找出自己的不足并加以改进。',
        '3. 保持联系：如果面试官给了你联系方式，可以在适当的时候保持联系，但不要过于频繁。',
        '4. 继续寻找其他机会：不要因为一次面试而停止寻找其他机会，保持多线并行。'
      ]
    }
  ]);

  // 过滤问题
  const filteredQuestions = computed(() => {
    if (!searchQuery.value) {
      return questions.value.filter(q => q.category === activeCategory.value);
    }

    const query = searchQuery.value.toLowerCase();
    return questions.value.filter(q => {
      // 检查分类是否匹配
      const categoryMatch = q.category === activeCategory.value;

      // 检查标题是否包含搜索词
      const titleMatch = q.title.toLowerCase().includes(query);

      // 检查内容是否包含搜索词
      let contentMatch = false;
      if (q.type === 'note' && q.content) {
        contentMatch = q.content.some(para => para.toLowerCase().includes(query));
      } else if (q.answer) {
        contentMatch = q.answer.some(para => para.toLowerCase().includes(query));
      }

      return categoryMatch && (titleMatch || contentMatch);
    });
  });

  // 滚动到顶部
  const scrollToTop = () => {
    uni.pageScrollTo({
      scrollTop: 0,
      duration: 300
    });
  };
</script>

<style scoped>
  /* 全局样式 */
  .container {
    max-width: 1200px;
    margin: 0 auto;
  }

  /* 动画效果 */
  @keyframes fadeIn {
    from {
      opacity: 0;
      transform: translateY(-10px);
    }

    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  .animate-fadeIn {
    animation: fadeIn 0.3s ease-out forwards;
  }

  /* 代码样式 */
  pre {
    font-family: 'Consolas', 'Monaco', monospace;
    font-size: 14px;
    line-height: 1.5;
  }

  /* 解决 prose 样式冲突 */
  :deep(.prose) {
    max-width: 100% !important;
  }

  :deep(.prose p) {
    margin-bottom: 1rem !important;
  }

  /* 深色模式适配 */
  @media (prefers-color-scheme: dark) {
    :root {
      color-scheme: dark;
    }
  }
</style>